#include "stdafx.h"
#include "utils.h"

using namespace std;

//------------------------------------------------------------------------------

double CStopWatch::LIToSecs(LARGE_INTEGER & L)
{
	return ((double)L.QuadPart / (double)this->frequency.QuadPart);
}

CStopWatch::CStopWatch()
{
	this->start.QuadPart = 0;
	this->stop.QuadPart = 0;
	QueryPerformanceFrequency(&this->frequency);
}

void CStopWatch::startTimer()
{
	QueryPerformanceCounter(&this->start);
}

void CStopWatch::stopTimer()
{
	QueryPerformanceCounter(&stop);
}

double CStopWatch::getElapsedTime()
{
	LARGE_INTEGER time;
	time.QuadPart = this->stop.QuadPart - this->start.QuadPart;
	return LIToSecs(time);
}

//------------------------------------------------------------------------------

CBenchmarkResult::CBenchmarkResult(std::uint32_t repeats, double totalTimeInSecs)
	: repeats(repeats), totalTime(totalTimeInSecs)
{}

std::uint32_t CBenchmarkResult::GetRepeats() const
{
	return this->repeats;
}

double CBenchmarkResult::TotalTimeInSeconds() const
{
	return this->totalTime;
}

double CBenchmarkResult::GetTimePerCall() const
{
	return this->totalTime / this->repeats;
}

//------------------------------------------------------------------------------

CBenchmarkResult BenchmarkFunction(std::function<void()> func, uint32_t repeats)
{
	CStopWatch sw;
	sw.startTimer();
	for (uint32_t i = 0; i < repeats; ++i)
	{
		func();
	}

	sw.stopTimer();

	return CBenchmarkResult(repeats, sw.getElapsedTime());
}

//------------------------------------------------------------------------------

void split(const std::string& str, const std::string& delim, std::vector<std::string>& parts)
{
	size_t start, end = 0;
	while (end < str.size())
	{
		start = end;
		while (start < str.size() && (delim.find(str[start]) != string::npos))
		{
			start++;  // skip initial whitespace
		}

		end = start;
		while (end < str.size() && (delim.find(str[end]) == string::npos))
		{
			end++; // skip to end of word
		}

		if (end - start != 0) {  // just ignore zero-length strings.
			parts.push_back(std::string(str, start, end - start));
		}
	}
}

void split(const std::wstring& str, const std::wstring& delim, std::vector<std::wstring>& parts)
{
	size_t start, end = 0;
	while (end < str.size())
	{
		start = end;
		while (start < str.size() && (delim.find(str[start]) != string::npos))
		{
			start++;  // skip initial whitespace
		}

		end = start;
		while (end < str.size() && (delim.find(str[end]) == string::npos))
		{
			end++; // skip to end of word
		}

		if (end - start != 0) {  // just ignore zero-length strings.
			parts.push_back(std::wstring(str, start, end - start));
		}
	}
}

bool isEmpty(const wchar_t* s)
{
	for (;;++s)
	{
		switch (*s)
		{
			case L'\0':
				return true;
			case L' ':
			case L'\t':
			case L'\n':
			case L'\r':
			case L'\f':
			case L'\v':
				continue;
		}

		return false;
	}
}

std::wstring realPath(const wchar_t* p)
{
	DWORD dw = GetFullPathName(p, 0, NULL, NULL);
	if (dw == 0)
	{
		return std::wstring();
	}

	wchar_t* absPath = (wchar_t*)_malloca(sizeof(wchar_t)*dw);
	dw = GetFullPathName(p, dw, absPath, NULL);
	if (dw == 0)
	{
		_freea(absPath);
		return std::wstring();
	}

	DWORD ftyp = GetFileAttributes(absPath);
	if ((ftyp&FILE_ATTRIBUTE_DIRECTORY) == 0)
	{
		_freea(absPath);
		return std::wstring();
	}

	auto str = std::wstring(absPath);
	_freea(absPath);
	return str;
}